package Both;

/**
 * Polytech' Nice - Sophia Antipolis / SI3 / Projet de fin de semestre
 * Annee 2011_2012
 * 
 * Reservation de transports en commun
 * 
 * Package Both
 * 
 * Classe Billet : modelisation d'un billet de reservation
 * 
 * @author J. Harnetiaux et N. Potier
 */

import java.io.FileWriter;
import java.io.IOException;
import java.io.Serializable;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;

public class Billet implements Serializable {

    private static int id = 0;

    private ArrayList<Trajet> trajets;
    private double prix;
    private ProfilPassager profil;
    private TypeBillet typeBillet;
    private int nbPlace;
    private int idBillet;

    private HashMap<String, Double> services;

    /**
     * Constructeur par d�faut
     */
    public Billet() {
        this.trajets = new ArrayList<Trajet>();
        this.prix = 0;
        this.profil = null;
        this.typeBillet = null;
    }

    /**
     * Constructeur normal
     * 
     * @param trajet
     *            Trajet effectue
     * @param profil
     *            Profil du passager (enfant, etudiant, senior, etc.)
     * @param typeBillet
     *            Type du billet (modifiable, non modifiable, etc.)
     * @param services
     *            Services souscrits pour ce trajet
     * @param nbPlace
     *            Nombre de places reservees
     */

    public Billet(ArrayList<Trajet> trajet, ProfilPassager profil,
            TypeBillet typeBillet, HashMap<String, Double> services, int nbPlace) {

        this.trajets = (ArrayList<Trajet>) trajet.clone();
        this.profil = profil;
        this.typeBillet = typeBillet;

        this.nbPlace = nbPlace;

        this.services = services;

        Billet.id++;
        this.idBillet = Billet.id;

        // Calculer le prix du billet
        //
        this.prix = this.calculerPrix();
    }

    /**
     * @return le trajet effectue
     */
    public ArrayList<Trajet> getTrajets() {
        return trajets;
    }

    /**
     * @return le prix du billet
     */
    public double getPrix() {
        return prix;
    }

    /**
     * @return le profil du passager
     */
    public ProfilPassager getProfil() {
        return profil;
    }

    /**
     * @return le type de billet
     */
    public TypeBillet getTypeBillet() {
        return typeBillet;
    }

    /**
     * @return les services souscris
     */
    public HashMap<String, Double> getServices() {
        return services;
    }

    /**
     * @param trajet
     *            Defini le trajet effectue
     */
    public void setTrajet(ArrayList<Trajet> trajets) {
        this.trajets = trajets;
    }

    /**
     * @param prix
     *            Defini le prix du billet
     */
    public void setPrix(double prix) {
        this.prix = prix;
    }

    /**
     * @param profil
     *            Defini le profil du passager
     */
    public void setProfil(ProfilPassager profil) {
        this.profil = profil;
    }

    /**
     * @param typeBillet
     *            Defini le type du billet
     */
    public void setTypeBillet(TypeBillet typeBillet) {
        this.typeBillet = typeBillet;
    }

    /**
     * @param services
     *            Defini les services souscris
     */
    public void setServices(HashMap<String, Double> services) {
        this.services = services;
    }

    /**
     * Calcule le prix du billet en fonction : - de la distance du trajet ; -
     * des services souscris ; - du profil du passager ; - du type de transport.
     * 
     * @return le prix du billet
     */
    public double calculerPrix() {
        // Definir le prix du billet de base
        //
        double prix = 0;

        // Multiplier par le coefficient associe a la distance du trajet
        //
        for (Trajet t : trajets) {
            prix += t.getTransport().getType().getTarif() * t.getDistance();
        }

        // Multiplier par le coefficient associe au profil du passager
        //
        prix *= this.profil.getProfil();

        // Ajouter le prix pour les services souscris
        //
        if (services != null) {
            for (String key : services.keySet()) {
                prix += services.get(key);
            }
        }

        // Multiplier par le coefficient associe au type du billet
        //
        prix *= this.typeBillet.getType();

        // Retourner le prix total du billet
        //
        return prix;
    }

    /**
     * Surcharge de la methode equals L'ID d'un billet etant unique, la valeur
     * de celui-ci n'est pas prise en compte dans la comparaison
     */
    @Override
    public boolean equals(Object arg0) {

        // S'assurer de la validite du parametre
        //
        if (arg0 == null || !(arg0 instanceof Billet))
            return false;

        // Construire le billet associe au parametre
        //
        Billet compare = (Billet) arg0;

        // S'assurer de l'egalite de la liste des trajets
        //
        if (trajets.size() != compare.trajets.size())
            return false;
        for (int i = 0; i < trajets.size(); i++) {
            if (!trajets.get(i).equals(compare.trajets.get(i)))
                return false;
        }

        // S'assurer de l'egalite du prix
        //
        if (prix != compare.prix)
            return false;

        // S'assurer de l'egalite du profil du passager
        //
        if (!profil.equals(compare.profil))
            return false;

        // S'assurer de l'egalite du type de billet
        //
        if (!typeBillet.equals(compare.typeBillet))
            return false;

        // S'assurer de l'egalite du nombre de places
        //
        if (nbPlace != compare.nbPlace)
            return false;

        // S'assurer de l'egalite des services souscrits
        //
        if (!Services.equalsHasMap(services, compare.services))
            return false;

        return true;

    }

    /**
     * Générer le récapitulatifs de la reservation dans un fihcier html
     * 
     * @throws IOException
     * 
     */
    public void genererRecapHTML() {
        String nomFichier = "Reservation-" + this.getIdBillet() + ".html";

        // Recuperer le nombre de trajet
        //
        int nbTrajets = trajets.size();

        int i = 0;
        int j = 0;

        Writer wRecap;
        try {
            wRecap = new FileWriter(nomFichier);

            String html = "<!DOCTYPE html>\n"
                    + "<html>\n"
                    + "\t<head>\n"
                    + "\t\t<meta charset=\"utf-8\">\n"
                    + "\t<title>Billet n°"
                    + this.getIdBillet()
                    + "</title>\n"
                    + "\t</head>\n"
                    + "\t<body>\n"
                    + "\t\t<h1>Récapitulatif de votre réservation :</h1>\n"
                    + "\t\t <b>Trajet :</b> \n</br></br>"
                    + "\t\t\t <b> Type Transport :</b> "
                    + this.trajets.get(i).getTransport().getType()
                    + "\n<dd>"
                    + this.trajets.get(i).getVilleDepart()
                    + " "
                    + this.trajets.get(i).getFormatedDate(
                            this.trajets.get(i).getDateDepart().getTime());

            // Decomponser l'ensemble des trajets pour distinguer les différents
            // transport utilisé
            //
            while (i < nbTrajets) {
                while (i < nbTrajets
                        && this.trajets.get(i).getTransport().equals(
                                this.trajets.get(j).getTransport())) {
                    j = i;
                    i++;
                }

                html += "\t"
                        + this.trajets.get(j).getVilleArrive()
                        + " "
                        + this.trajets.get(j).getFormatedDate(
                                this.trajets.get(j).getDateArrive().getTime())
                        + "</dd></br>";

                j++;

                if (j >= nbTrajets) {
                    break;
                } else {
                    html += "\t\t\t</br><b>Type Transport :</b> "
                            + this.trajets.get(i).getTransport().getType()
                            + "\n<dd> "
                            + this.trajets.get(i).getVilleDepart()
                            + " "
                            + this.trajets.get(i).getFormatedDate(
                                    this.trajets.get(i).getDateDepart()
                                            .getTime());
                }

            }

            html += "\t\t<b>Profil Passsager :</b>" + this.profil + "</br>\n"
                    + "\t\t<b>TypeBillet : </b>" + this.typeBillet + "</br>\n"
                    + "\t\t<b>Nombre de place : </b>" + this.nbPlace
                    + "</br>\n" + "\t\t<b>Prix : </b>" + this.prix + "</br>\n"
                    + "\t</body>\n" + "</html>";

            wRecap.write(html);

            wRecap.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * @return the idBillet
     */
    public int getIdBillet() {
        return idBillet;
    }

    /**
     * @param idBillet
     *            the idBillet to set
     */
    public void setIdBillet(int idBillet) {
        this.idBillet = idBillet;
    }
}
